package org.gdstash.character;

import org.gdstash.file.GDReader;
import org.gdstash.file.GDWriter;
import org.gdstash.util.FileVersionException;
import org.gdstash.util.GDMsgFormatter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class GDCharShrineList {
    private static final byte[] SHRINE_01_BURIAL_HILL;
    private static final byte[] SHRINE_01_DEVILS_AQUIFIER;
    private static final byte[] SHRINE_01_WIGHTMIRE_CAVERN;
    private static final byte[] SHRINE_01_FLOODED_PASSAGE;
    private static final byte[] SHRINE_01_BURIAL_CAVE;
    private static final byte[] SHRINE_01_HALLOWED_HILL;
    private static final byte[] SHRINE_01_BURRWITCH_ESTATES;
    private static final byte[] SHRINE_01_UNDERGROUND_TRANSIT;
    private static final byte[] SHRINE_01_CRAIGS_CRAGS;
    private static final byte[] SHRINE_01_GUARDIAN_DREEG;
    private static final byte[] SHRINE_01_TEMPLE_THREE;
    private static final byte[] SHRINE_02_SPINED_COVE;
    private static final byte[] SHRINE_02_ROCKY_COAST;
    private static final byte[] SHRINE_02_CRONLEYS_HIDEOUT;
    private static final byte[] SHRINE_02_OLD_ARKOVIA;
    private static final byte[] SHRINE_02_ARKOVIAN_UNDERCITY;
    private static final byte[] SHRINE_02_BROKEN_HILLS;
    private static final byte[] SHRINE_02_STEPS_OF_TORMENT;
    private static final byte[] SHRINE_03_MOUNTAIN_DEEPS;
    private static final byte[] SHRINE_03_FORGOTTEN_DEPTHS;
    private static final byte[] SHRINE_03_TYRANTS_HOLD;
    private static final byte[] SHRINE_03_INFESTED_FARMS;
    private static final byte[] SHRINE_03_DEN_OF_THE_LOST;
    private static final byte[] SHRINE_03_CONFLAGRATION;
    private static final byte[] SHRINE_03_PORT_VALBURY;
    private static final byte[] SHRINE_03_BLOOD_GROVE;
    private static final byte[] SHRINE_03_STONEREND_QUARRY;
    private static final byte[] SHRINE_03_VILLAGE_OF_DARKVALE;
    private static final byte[] SHRINE_04_ASTERKARN_VALLEY;
    private static final byte[] SHRINE_04_MOGDROGENS_SHRINE;
    private static final byte[] SHRINE_04_TOMB_OF_THE_DAMNED;
    private static final byte[] SHRINE_04_GATES_OF_NECROPOLIS;
    private static final byte[] SHRINE_04_BLACK_SEPULCHER;
    private static final byte[] SHRINE_04_BASTION_OF_CHAOS;
    private static final byte[] SHRINE_04_TOMB_OF_WATCHERS;
    private static final byte[] SHRINE_04_SANCTUM_OF_THE_IMMORTAL;
    private static final byte[] SHRINE_05_GLOOMWALD_CROSSING;
    private static final byte[] SHRINE_05_ANCIENT_GROVE;
    private static final byte[] SHRINE_05_UGDENBOG_KR_VALL;
    private static final byte[] SHRINE_05_TOMB_OF_UGDAL;
    private static final byte[] SHRINE_05_TOMB_OF_UGDAL_ELITE;
    private static final byte[] SHRINE_05_BARROWHOLM_MINE;
    private static final byte[] SHRINE_05_DESOLATE_WASTES;
    private static final byte[] SHRINE_05_MALMOUTH;
    private static final byte[] SHRINE_05_RANSACKED_LIGHTHOUSE;
    private static final byte[] SHRINE_05_CROWN_HILL;
    private static final byte[] SHRINE_05_INFESTATION;
    private static final byte[] SHRINE_05_SANCTUM_OF_THE_CHOSEN;
    private static final byte[] SHRINE_06_SHATTERED_REALMS;
    private static final byte[] SHRINE_06_TEMPLE_OSYR;
    private static final byte[] SHRINE_06_KORVAN_OASIS;
    private static final byte[] SHRINE_06_CAIRAN_DOCKS;
    private static final byte[] SHRINE_06_SANDBLOWN_RUINS;
    private static final byte[] SHRINE_06_SANCTUARY_HORRAN;
    private static final byte[] SHRINE_06_RUINS_ABYD;
    private static final byte[] SHRINE_06_VALLEY_CHOSEN;
    private static final byte[] SHRINE_06_SUNWARD_SPIRE;
    private static final byte[] SHRINE_06_ELDRITCH_SUN;
    private static final byte[] SHRINE_06_SECRET_QUEST;
    private static final byte[] SHRINE_06_LOST_OASIS;
    public static final GDCharUID UID_SHRINE_01_BURIAL_HILL;
    public static final GDCharUID UID_SHRINE_01_DEVILS_AQUIFIER;
    public static final GDCharUID UID_SHRINE_01_WIGHTMIRE_CAVERN;
    public static final GDCharUID UID_SHRINE_01_FLOODED_PASSAGE;
    public static final GDCharUID UID_SHRINE_01_BURIAL_CAVE;
    public static final GDCharUID UID_SHRINE_01_HALLOWED_HILL;
    public static final GDCharUID UID_SHRINE_01_BURRWITCH_ESTATES;
    public static final GDCharUID UID_SHRINE_01_UNDERGROUND_TRANSIT;
    public static final GDCharUID UID_SHRINE_01_CRAIGS_CRAGS;
    public static final GDCharUID UID_SHRINE_01_GUARDIAN_DREEG;
    public static final GDCharUID UID_SHRINE_01_TEMPLE_THREE;
    public static final GDCharUID UID_SHRINE_02_SPINED_COVE;
    public static final GDCharUID UID_SHRINE_02_ROCKY_COAST;
    public static final GDCharUID UID_SHRINE_02_CRONLEYS_HIDEOUT;
    public static final GDCharUID UID_SHRINE_02_OLD_ARKOVIA;
    public static final GDCharUID UID_SHRINE_02_ARKOVIAN_UNDERCITY;
    public static final GDCharUID UID_SHRINE_02_BROKEN_HILLS;
    public static final GDCharUID UID_SHRINE_02_STEPS_OF_TORMENT;
    public static final GDCharUID UID_SHRINE_03_MOUNTAIN_DEEPS;
    public static final GDCharUID UID_SHRINE_03_FORGOTTEN_DEPTHS;
    public static final GDCharUID UID_SHRINE_03_TYRANTS_HOLD;
    public static final GDCharUID UID_SHRINE_03_INFESTED_FARMS;
    public static final GDCharUID UID_SHRINE_03_DEN_OF_THE_LOST;
    public static final GDCharUID UID_SHRINE_03_CONFLAGRATION;
    public static final GDCharUID UID_SHRINE_03_PORT_VALBURY;
    public static final GDCharUID UID_SHRINE_03_BLOOD_GROVE;
    public static final GDCharUID UID_SHRINE_03_STONEREND_QUARRY;
    public static final GDCharUID UID_SHRINE_03_VILLAGE_OF_DARKVALE;
    public static final GDCharUID UID_SHRINE_04_ASTERKARN_VALLEY;
    public static final GDCharUID UID_SHRINE_04_MOGDROGENS_SHRINE;
    public static final GDCharUID UID_SHRINE_04_TOMB_OF_THE_DAMNED;
    public static final GDCharUID UID_SHRINE_04_GATES_OF_NECROPOLIS;
    public static final GDCharUID UID_SHRINE_04_BLACK_SEPULCHER;
    public static final GDCharUID UID_SHRINE_04_BASTION_OF_CHAOS;
    public static final GDCharUID UID_SHRINE_04_TOMB_OF_WATCHERS;
    public static final GDCharUID UID_SHRINE_04_SANCTUM_OF_THE_IMMORTAL;
    public static final GDCharUID UID_SHRINE_05_GLOOMWALD_CROSSING;
    public static final GDCharUID UID_SHRINE_05_ANCIENT_GROVE;
    public static final GDCharUID UID_SHRINE_05_UGDENBOG_KR_VALL;
    public static final GDCharUID UID_SHRINE_05_TOMB_OF_UGDAL;
    public static final GDCharUID UID_SHRINE_05_TOMB_OF_UGDAL_ELITE;
    public static final GDCharUID UID_SHRINE_05_BARROWHOLM_MINE;
    public static final GDCharUID UID_SHRINE_05_DESOLATE_WASTES;
    public static final GDCharUID UID_SHRINE_05_MALMOUTH;
    public static final GDCharUID UID_SHRINE_05_RANSACKED_LIGHTHOUSE;
    public static final GDCharUID UID_SHRINE_05_CROWN_HILL;
    public static final GDCharUID UID_SHRINE_05_INFESTATION;
    public static final GDCharUID UID_SHRINE_05_SANCTUM_OF_THE_CHOSEN;
    public static final GDCharUID UID_SHRINE_06_SHATTERED_REALMS;
    public static final GDCharUID UID_SHRINE_06_TEMPLE_OSYR;
    public static final GDCharUID UID_SHRINE_06_CAIRAN_DOCKS;
    public static final GDCharUID UID_SHRINE_06_SANCTUARY_HORRAN;
    public static final GDCharUID UID_SHRINE_06_RUINS_ABYD;
    public static final GDCharUID UID_SHRINE_06_VALLEY_CHOSEN;
    public static final GDCharUID UID_SHRINE_06_SUNWARD_SPIRE;
    public static final GDCharUID UID_SHRINE_06_ELDRITCH_SUN;
    public static final GDCharUID UID_SHRINE_06_KORVAN_OASIS;
    public static final GDCharUID UID_SHRINE_06_SANDBLOWN_RUINS;
    public static final GDCharUID UID_SHRINE_06_SECRET_QUEST;
    public static final GDCharUID UID_SHRINE_06_LOST_OASIS;
    public static final GDCharUID UID_SHRINE_07_FROSTVEIL_HIGHLANDS;
    public static final GDCharUID UID_SHRINE_07_FREYOLL_VALLEY;
    public static final GDCharUID UID_SHRINE_07_ULOS_SPRINGS;
    public static final GDCharUID UID_SHRINE_07_DREAD_WASTES;
    public static final GDCharUID UID_SHRINE_07_SCARSTONE;
    public static final GDCharUID UID_SHRINE_07_AURORA_PEAKS;
    public static final GDCharUID UID_SHRINE_07_DRANG_GAL;
    public static final GDCharUID UID_SHRINE_07_TEMPLE_NERF;
    private static final byte[] SHRINE_07_LOST_OASIS;
    private static final int VERSION = 2;
    private static final int BLOCK = 17;

    static {
        SHRINE_01_BURIAL_HILL = new byte[]{-102, -127, -12, 45, -87, 76, -31, 35, 71, -82, -23, -117, 40, -45, 80, 69};
        SHRINE_01_DEVILS_AQUIFIER = new byte[]{97, 8, 108, -79, -49, 71, -42, -82, 79, -88, -115, -120, 45, -58, 82, 32};
        SHRINE_01_WIGHTMIRE_CAVERN = new byte[]{58, -113, -123, 73, -84, 74, -91, -117, 102, -102, 124, -76, 17, 109, 33, 80};
        SHRINE_01_FLOODED_PASSAGE = new byte[]{-83, 9, 86, 92, 39, 66, 43, 68, -126, 102, 64, -85, 54, 56, 123, -101};
        SHRINE_01_BURIAL_CAVE = new byte[]{-54, 27, 4, 32, 54, 73, 46, 103, -105, 2, 101, -86, -100, -11, -5, 126};
        SHRINE_01_HALLOWED_HILL = new byte[]{-21, -43, -83, -116, -82, 71, -111, -85, 88, -40, 42, -71, -28, 44, -71, -93};
        SHRINE_01_BURRWITCH_ESTATES = new byte[]{-119, -19, 19, -58, 17, 73, 68, 119, -121, -27, -61, -112, -1, 7, 18, 106};
        SHRINE_01_UNDERGROUND_TRANSIT = new byte[]{111, -65, 4, -14, 42, 66, 4, -81, -39, 122, -54, -122, -120, 15, -55, 10};
        SHRINE_01_CRAIGS_CRAGS = new byte[]{-69, -34, -50, 89, 66, 65, 96, 114, 74, -54, 73, -87, 75, 97, 5, 16};
        SHRINE_01_GUARDIAN_DREEG = new byte[]{89, 92, -60, 101, -82, 73, -93, -9, -122, 111, 21, -101, -92, 60, 102, -128};
        SHRINE_01_TEMPLE_THREE = new byte[]{64, -6, -1, 91, 10, 71, -122, -33, 81, -44, 90, -117, -50, -113, -74, 1};
        SHRINE_02_SPINED_COVE = new byte[]{-53, -29, 96, 55, 72, 65, 4, 31, 18, -95, 35, -108, -49, 67, -58, 51};
        SHRINE_02_ROCKY_COAST = new byte[]{-99, 8, 21, 3, 33, 67, -78, 18, -57, 18, -12, -77, -40, 66, -119, 75};
        SHRINE_02_CRONLEYS_HIDEOUT = new byte[]{-51, -3, -112, -122, 43, 70, 54, -47, 115, 89, 13, -67, -2, -40, 107, 61};
        SHRINE_02_OLD_ARKOVIA = new byte[]{-115, 21, 10, 80, -66, 77, -86, -19, 86, -71, 57, -123, 71, 86, 77, -81};
        SHRINE_02_ARKOVIAN_UNDERCITY = new byte[]{-82, 36, 110, 17, 3, 70, 67, -61, 37, 27, -73, -122, 42, 0, 78, 51};
        SHRINE_02_BROKEN_HILLS = new byte[]{-99, -83, 120, 101, 6, 69, -39, -101, 125, -26, -19, -79, -61, 46, 95, -128};
        SHRINE_02_STEPS_OF_TORMENT = new byte[]{50, -28, -6, 11, -81, 70, -64, 7, 77, -125, 38, -95, -70, 41, -8, -28};
        SHRINE_03_MOUNTAIN_DEEPS = new byte[]{-21, 33, -60, -20, 27, 79, 55, -77, -46, 72, 50, -80, 64, -54, 41, 67};
        SHRINE_03_FORGOTTEN_DEPTHS = new byte[]{62, 109, -82, -116, -18, 71, 107, -87, 34, 108, -79, -71, 72, 24, 106, 126};
        SHRINE_03_TYRANTS_HOLD = new byte[]{-61, -126, -13, 108, 41, 65, 102, -96, -125, -63, -80, -76, 29, -27, -94, 42};
        SHRINE_03_INFESTED_FARMS = new byte[]{-96, 78, -78, -47, -110, 67, 96, 98, -54, -36, -127, -73, -32, -110, 68, -40};
        SHRINE_03_DEN_OF_THE_LOST = new byte[]{-82, -49, 65, 101, 59, 68, 119, 48, -45, 17, -13, -86, 12, 74, -57, -97};
        SHRINE_03_CONFLAGRATION = new byte[]{-63, 103, -126, 74, -109, 70, -84, 4, 73, -12, -94, -81, 66, -78, 82, 102};
        SHRINE_03_PORT_VALBURY = new byte[]{125, -110, -26, -73, -109, 78, -11, -103, 68, -125, 74, -102, 20, 59, 57, -118};
        SHRINE_03_BLOOD_GROVE = new byte[]{-27, 73, -97, -11, -114, 76, 58, 12, 22, 30, -20, -93, -10, -103, 97, -95};
        SHRINE_03_STONEREND_QUARRY = new byte[]{81, 16, -89, -54, 76, 64, -53, -114, 21, -46, 54, -76, -70, 114, -101, 45};
        SHRINE_03_VILLAGE_OF_DARKVALE = new byte[]{87, 102, 85, -2, -104, 75, -109, -56, 115, -13, 27, -71, 84, 53, 55, -86};
        SHRINE_04_ASTERKARN_VALLEY = new byte[]{46, 44, 37, -84, -51, 72, 36, -65, -33, -50, -101, -112, 8, -30, -98, -87};
        SHRINE_04_MOGDROGENS_SHRINE = new byte[]{13, -62, -115, 29, 40, 71, 97, 41, -22, -20, 41, -117, 4, -72, 102, 102};
        SHRINE_04_TOMB_OF_THE_DAMNED = new byte[]{-125, -87, -80, -33, -51, 74, -56, 74, -30, -23, 14, -91, -85, -92, -78, -59};
        SHRINE_04_GATES_OF_NECROPOLIS = new byte[]{-114, -5, -34, -106, 126, 69, -90, 49, -122, -8, -11, -120, -104, 11, 114, -112};
        SHRINE_04_BLACK_SEPULCHER = new byte[]{66, -95, 91, -100, -105, 75, 62, -49, -24, -35, -97, -111, 68, -64, 24, -119};
        SHRINE_04_BASTION_OF_CHAOS = new byte[]{-27, 2, 60, 14, 42, 65, -27, -102, 88, 91, 55, -121, 77, 122, 108, -86};
        SHRINE_04_TOMB_OF_WATCHERS = new byte[]{28, -23, 71, -106, 127, 69, 90, -74, -78, -18, -75, -88, 96, 71, 3, -119};
        SHRINE_04_SANCTUM_OF_THE_IMMORTAL = new byte[]{24, -122, 98, -122, 0, 75, 72, 94, -105, -92, -26, -80, 35, 77, 77, -95};
        SHRINE_05_GLOOMWALD_CROSSING = new byte[]{-36, 8, 74, -43, 78, 73, 104, 5, 33, -117, -89, -120, 104, -39, 9, 110};
        SHRINE_05_ANCIENT_GROVE = new byte[]{-124, -72, -91, 0, -72, 71, 118, -128, -94, 88, 26, -116, 56, 20, -100, 113};
        SHRINE_05_UGDENBOG_KR_VALL = new byte[]{58, -108, 120, 117, -14, 67, -29, -82, 78, 70, -1, -105, -45, -7, -21, -88};
        SHRINE_05_TOMB_OF_UGDAL = new byte[]{-104, -67, -127, 26, -116, 66, 24, -70, 3, -68, -13, -68, -66, -25, -45, 52};
        SHRINE_05_TOMB_OF_UGDAL_ELITE = new byte[]{83, -101, 113, -66, 11, 77, -89, 10, 69, -61, 66, -99, 8, 49, 126, 80};
        SHRINE_05_BARROWHOLM_MINE = new byte[]{89, 15, -124, 2, -49, 74, 67, 87, -117, -44, -117, -102, -115, 112, 72, 107};
        SHRINE_05_DESOLATE_WASTES = new byte[]{49, 2, -100, 64, -77, 76, 79, 73, -106, 125, 47, -107, -104, 99, 99, 8};
        SHRINE_05_MALMOUTH = new byte[]{54, 116, -47, 41, -56, 66, 109, -69, 67, 43, 33, -77, -10, -42, 75, 16};
        SHRINE_05_RANSACKED_LIGHTHOUSE = new byte[]{13, 71, 9, -2, 48, 71, 39, -4, -91, 52, 84, -79, 93, 40, 100, -81};
        SHRINE_05_CROWN_HILL = new byte[]{-64, 36, 66, 36, -72, 71, 90, 13, 76, 114, 107, -77, 112, 121, -46, -91};
        SHRINE_05_INFESTATION = new byte[]{25, 117, 46, -71, 32, 64, -50, -78, -116, 79, 18, -67, 62, -118, -40, 103};
        SHRINE_05_SANCTUM_OF_THE_CHOSEN = new byte[]{-88, -53, 57, 29, 113, 65, 48, 122, -44, -44, -34, -118, 97, -115, -28, -108};
        SHRINE_06_SHATTERED_REALMS = new byte[]{-67, -6, -79, -114, 32, 64, 2, 109, -106, 81, -6, -84, -41, -42, -28, -23};
        SHRINE_06_TEMPLE_OSYR = new byte[]{118, 58, 60, -99, 36, 68, -10, 2, 117, 11, -62, -70, -27, 30, 52, -120};
        SHRINE_06_KORVAN_OASIS = new byte[]{-99, 77, -40, -127, -65, 79, -126, 82, -66, 23, 52, -73, -22, 61, -49, -88};
        SHRINE_06_CAIRAN_DOCKS = new byte[]{-10, -46, -74, -17, -18, 72, -110, 104, 16, 17, -15, -107, -39, -29, 68, -10};
        SHRINE_06_SANDBLOWN_RUINS = new byte[]{-10, -86, -66, -47, -119, 73, -20, -124, 27, 43, 80, -96, 41, 102, -126, 30};
        SHRINE_06_SANCTUARY_HORRAN = new byte[]{71, -72, -19, -73, -97, 77, 6, 24, -70, 109, -109, -80, 47, -49, -79, -15};
        SHRINE_06_RUINS_ABYD = new byte[]{2, 104, -112, 8, 24, 68, -47, -118, -3, 23, -107, -86, 118, -3, -29, 35};
        SHRINE_06_VALLEY_CHOSEN = new byte[]{-70, 70, -88, 102, -56, 71, 44, 127, -71, -66, -101, -117, -4, 127, -93, -101};
        SHRINE_06_SUNWARD_SPIRE = new byte[]{54, 8, 127, -76, -37, 71, 46, -66, 49, 32, 18, -113, 75, -23, 23, -91};
        SHRINE_06_ELDRITCH_SUN = new byte[]{22, -101, 114, -123, -100, 76, 30, 122, 57, -10, -104, -112, 78, 0, -125, 89};
        SHRINE_06_SECRET_QUEST = new byte[]{-79, -110, 43, 5, 44, 67, 65, 71, 81, -33, 45, -103, 33, -121, -96, 79};
        SHRINE_06_LOST_OASIS = new byte[]{24, 38, 7, 13, 37, 75, 38, 125, -67, -100, -12, -124, -42, -16, 85, 68};
        SHRINE_07_LOST_OASIS = new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
        UID_SHRINE_01_BURIAL_HILL = new GDCharUID(GDCharShrineList.SHRINE_01_BURIAL_HILL);
        UID_SHRINE_01_DEVILS_AQUIFIER = new GDCharUID(GDCharShrineList.SHRINE_01_DEVILS_AQUIFIER);
        UID_SHRINE_01_WIGHTMIRE_CAVERN = new GDCharUID(GDCharShrineList.SHRINE_01_WIGHTMIRE_CAVERN);
        UID_SHRINE_01_FLOODED_PASSAGE = new GDCharUID(GDCharShrineList.SHRINE_01_FLOODED_PASSAGE);
        UID_SHRINE_01_BURIAL_CAVE = new GDCharUID(GDCharShrineList.SHRINE_01_BURIAL_CAVE);
        UID_SHRINE_01_HALLOWED_HILL = new GDCharUID(GDCharShrineList.SHRINE_01_HALLOWED_HILL);
        UID_SHRINE_01_BURRWITCH_ESTATES = new GDCharUID(GDCharShrineList.SHRINE_01_BURRWITCH_ESTATES);
        UID_SHRINE_01_UNDERGROUND_TRANSIT = new GDCharUID(GDCharShrineList.SHRINE_01_UNDERGROUND_TRANSIT);
        UID_SHRINE_01_CRAIGS_CRAGS = new GDCharUID(GDCharShrineList.SHRINE_01_CRAIGS_CRAGS);
        UID_SHRINE_01_GUARDIAN_DREEG = new GDCharUID(GDCharShrineList.SHRINE_01_GUARDIAN_DREEG);
        UID_SHRINE_01_TEMPLE_THREE = new GDCharUID(GDCharShrineList.SHRINE_01_TEMPLE_THREE);
        UID_SHRINE_02_SPINED_COVE = new GDCharUID(GDCharShrineList.SHRINE_02_SPINED_COVE);
        UID_SHRINE_02_ROCKY_COAST = new GDCharUID(GDCharShrineList.SHRINE_02_ROCKY_COAST);
        UID_SHRINE_02_CRONLEYS_HIDEOUT = new GDCharUID(GDCharShrineList.SHRINE_02_CRONLEYS_HIDEOUT);
        UID_SHRINE_02_OLD_ARKOVIA = new GDCharUID(GDCharShrineList.SHRINE_02_OLD_ARKOVIA);
        UID_SHRINE_02_ARKOVIAN_UNDERCITY = new GDCharUID(GDCharShrineList.SHRINE_02_ARKOVIAN_UNDERCITY);
        UID_SHRINE_02_BROKEN_HILLS = new GDCharUID(GDCharShrineList.SHRINE_02_BROKEN_HILLS);
        UID_SHRINE_02_STEPS_OF_TORMENT = new GDCharUID(GDCharShrineList.SHRINE_02_STEPS_OF_TORMENT);
        UID_SHRINE_03_MOUNTAIN_DEEPS = new GDCharUID(GDCharShrineList.SHRINE_03_MOUNTAIN_DEEPS);
        UID_SHRINE_03_FORGOTTEN_DEPTHS = new GDCharUID(GDCharShrineList.SHRINE_03_FORGOTTEN_DEPTHS);
        UID_SHRINE_03_TYRANTS_HOLD = new GDCharUID(GDCharShrineList.SHRINE_03_TYRANTS_HOLD);
        UID_SHRINE_03_INFESTED_FARMS = new GDCharUID(GDCharShrineList.SHRINE_03_INFESTED_FARMS);
        UID_SHRINE_03_DEN_OF_THE_LOST = new GDCharUID(GDCharShrineList.SHRINE_03_DEN_OF_THE_LOST);
        UID_SHRINE_03_CONFLAGRATION = new GDCharUID(GDCharShrineList.SHRINE_03_CONFLAGRATION);
        UID_SHRINE_03_PORT_VALBURY = new GDCharUID(GDCharShrineList.SHRINE_03_PORT_VALBURY);
        UID_SHRINE_03_BLOOD_GROVE = new GDCharUID(GDCharShrineList.SHRINE_03_BLOOD_GROVE);
        UID_SHRINE_03_STONEREND_QUARRY = new GDCharUID(GDCharShrineList.SHRINE_03_STONEREND_QUARRY);
        UID_SHRINE_03_VILLAGE_OF_DARKVALE = new GDCharUID(GDCharShrineList.SHRINE_03_VILLAGE_OF_DARKVALE);
        UID_SHRINE_04_ASTERKARN_VALLEY = new GDCharUID(GDCharShrineList.SHRINE_04_ASTERKARN_VALLEY);
        UID_SHRINE_04_MOGDROGENS_SHRINE = new GDCharUID(GDCharShrineList.SHRINE_04_MOGDROGENS_SHRINE);
        UID_SHRINE_04_TOMB_OF_THE_DAMNED = new GDCharUID(GDCharShrineList.SHRINE_04_TOMB_OF_THE_DAMNED);
        UID_SHRINE_04_GATES_OF_NECROPOLIS = new GDCharUID(GDCharShrineList.SHRINE_04_GATES_OF_NECROPOLIS);
        UID_SHRINE_04_BLACK_SEPULCHER = new GDCharUID(GDCharShrineList.SHRINE_04_BLACK_SEPULCHER);
        UID_SHRINE_04_BASTION_OF_CHAOS = new GDCharUID(GDCharShrineList.SHRINE_04_BASTION_OF_CHAOS);
        UID_SHRINE_04_TOMB_OF_WATCHERS = new GDCharUID(GDCharShrineList.SHRINE_04_TOMB_OF_WATCHERS);
        UID_SHRINE_04_SANCTUM_OF_THE_IMMORTAL = new GDCharUID(GDCharShrineList.SHRINE_04_SANCTUM_OF_THE_IMMORTAL);
        UID_SHRINE_05_GLOOMWALD_CROSSING = new GDCharUID(GDCharShrineList.SHRINE_05_GLOOMWALD_CROSSING);
        UID_SHRINE_05_ANCIENT_GROVE = new GDCharUID(GDCharShrineList.SHRINE_05_ANCIENT_GROVE);
        UID_SHRINE_05_UGDENBOG_KR_VALL = new GDCharUID(GDCharShrineList.SHRINE_05_UGDENBOG_KR_VALL);
        UID_SHRINE_05_TOMB_OF_UGDAL = new GDCharUID(GDCharShrineList.SHRINE_05_TOMB_OF_UGDAL);
        UID_SHRINE_05_TOMB_OF_UGDAL_ELITE = new GDCharUID(GDCharShrineList.SHRINE_05_TOMB_OF_UGDAL_ELITE);
        UID_SHRINE_05_BARROWHOLM_MINE = new GDCharUID(GDCharShrineList.SHRINE_05_BARROWHOLM_MINE);
        UID_SHRINE_05_DESOLATE_WASTES = new GDCharUID(GDCharShrineList.SHRINE_05_DESOLATE_WASTES);
        UID_SHRINE_05_MALMOUTH = new GDCharUID(GDCharShrineList.SHRINE_05_MALMOUTH);
        UID_SHRINE_05_RANSACKED_LIGHTHOUSE = new GDCharUID(GDCharShrineList.SHRINE_05_RANSACKED_LIGHTHOUSE);
        UID_SHRINE_05_CROWN_HILL = new GDCharUID(GDCharShrineList.SHRINE_05_CROWN_HILL);
        UID_SHRINE_05_INFESTATION = new GDCharUID(GDCharShrineList.SHRINE_05_INFESTATION);
        UID_SHRINE_05_SANCTUM_OF_THE_CHOSEN = new GDCharUID(GDCharShrineList.SHRINE_05_SANCTUM_OF_THE_CHOSEN);
        UID_SHRINE_06_SHATTERED_REALMS = new GDCharUID(GDCharShrineList.SHRINE_06_SHATTERED_REALMS);
        UID_SHRINE_06_TEMPLE_OSYR = new GDCharUID(GDCharShrineList.SHRINE_06_TEMPLE_OSYR);
        UID_SHRINE_06_CAIRAN_DOCKS = new GDCharUID(GDCharShrineList.SHRINE_06_CAIRAN_DOCKS);
        UID_SHRINE_06_SANCTUARY_HORRAN = new GDCharUID(GDCharShrineList.SHRINE_06_SANCTUARY_HORRAN);
        UID_SHRINE_06_RUINS_ABYD = new GDCharUID(GDCharShrineList.SHRINE_06_RUINS_ABYD);
        UID_SHRINE_06_VALLEY_CHOSEN = new GDCharUID(GDCharShrineList.SHRINE_06_VALLEY_CHOSEN);
        UID_SHRINE_06_SUNWARD_SPIRE = new GDCharUID(GDCharShrineList.SHRINE_06_SUNWARD_SPIRE);
        UID_SHRINE_06_ELDRITCH_SUN = new GDCharUID(GDCharShrineList.SHRINE_06_ELDRITCH_SUN);
        UID_SHRINE_06_KORVAN_OASIS = new GDCharUID(GDCharShrineList.SHRINE_06_KORVAN_OASIS);
        UID_SHRINE_06_SANDBLOWN_RUINS = new GDCharUID(GDCharShrineList.SHRINE_06_SANDBLOWN_RUINS);
        UID_SHRINE_06_SECRET_QUEST = new GDCharUID(GDCharShrineList.SHRINE_06_SECRET_QUEST);
        UID_SHRINE_06_LOST_OASIS = new GDCharUID(GDCharShrineList.SHRINE_07_LOST_OASIS);
        UID_SHRINE_07_FROSTVEIL_HIGHLANDS = new GDCharUID(GDCharShrineList.SHRINE_07_LOST_OASIS);
        UID_SHRINE_07_FREYOLL_VALLEY = new GDCharUID(GDCharShrineList.SHRINE_07_LOST_OASIS);
        UID_SHRINE_07_ULOS_SPRINGS = new GDCharUID(GDCharShrineList.SHRINE_07_LOST_OASIS);
        UID_SHRINE_07_DREAD_WASTES = new GDCharUID(GDCharShrineList.SHRINE_07_LOST_OASIS);
        UID_SHRINE_07_SCARSTONE = new GDCharUID(GDCharShrineList.SHRINE_07_LOST_OASIS);
        UID_SHRINE_07_AURORA_PEAKS = new GDCharUID(GDCharShrineList.SHRINE_07_LOST_OASIS);
        UID_SHRINE_07_DRANG_GAL = new GDCharUID(GDCharShrineList.SHRINE_07_LOST_OASIS);
        UID_SHRINE_07_TEMPLE_NERF = new GDCharUID(GDCharShrineList.SHRINE_07_LOST_OASIS);
    }

    private int version;
    private ArrayList<List<GDCharUID>> uidLists;
    private GDChar gdc;
    private boolean changed;

    public GDCharShrineList(final GDChar gdc) {
        final int size = 6;
        this.uidLists = new ArrayList<List<GDCharUID>>(size);
        for (int i = 0; i < size; ++i) {
            this.uidLists.add(new LinkedList<GDCharUID>());
        }
        this.gdc = gdc;
    }

    public List<GDCharUID> getDiscoveredShrinesList(final int difficulty) {
        final List<GDCharUID> list = new LinkedList<GDCharUID>();
        if (difficulty < 0 || difficulty > 2) {
            return list;
        }
        return this.uidLists.get(2 * difficulty + 1);
    }

    public List<GDCharUID> getRestoredShrinesList(final int difficulty) {
        final List<GDCharUID> list = new LinkedList<GDCharUID>();
        if (difficulty < 0 || difficulty > 2) {
            return list;
        }
        return this.uidLists.get(2 * difficulty);
    }

    public boolean hasChanged() {
        return this.changed;
    }

    public void setDiscoveredShrinesList(final int difficulty, final List<GDCharUID> addList, final List<GDCharUID> removeList) {
        if (difficulty < 0 || difficulty > 2) {
            return;
        }
        final int index = 2 * difficulty + 1;
        final List<GDCharUID> shrines = this.uidLists.get(index);
        final List<GDCharUID> newList = new LinkedList<GDCharUID>();
        for (final GDCharUID uid : shrines) {
            if (!removeList.contains(uid)) {
                newList.add(uid);
            } else {
                this.changed = true;
            }
        }
        for (final GDCharUID uid : addList) {
            if (!newList.contains(uid)) {
                newList.add(uid);
                this.changed = true;
            }
        }
        this.uidLists.set(index, newList);
    }

    public void setRestoredShrinesList(final int difficulty, final List<GDCharUID> addList, final List<GDCharUID> removeList) {
        if (difficulty < 0 || difficulty > 2) {
            return;
        }
        final int index = 2 * difficulty;
        final List<GDCharUID> shrines = this.uidLists.get(index);
        final List<GDCharUID> newList = new LinkedList<GDCharUID>();
        for (final GDCharUID uid : shrines) {
            if (!removeList.contains(uid)) {
                newList.add(uid);
            } else {
                this.changed = true;
            }
        }
        for (final GDCharUID uid : addList) {
            if (!newList.contains(uid)) {
                newList.add(uid);
                this.changed = true;
            }
        }
        this.uidLists.set(index, newList);
        this.addDiscoveredShrinesList(difficulty, addList);
    }

    private void addDiscoveredShrinesList(final int difficulty, final List<GDCharUID> list) {
        if (difficulty < 0 || difficulty > 2) {
            return;
        }
        final List<GDCharUID> shrines = this.uidLists.get(2 * difficulty + 1);
        for (final GDCharUID uid : list) {
            if (!shrines.contains(uid)) {
                shrines.add(uid);
                this.changed = true;
            }
        }
    }

    public void read() throws IOException {
        int val = 0;
        final GDReader.Block block = new GDReader.Block();
        val = GDReader.readBlockStart(block);
        if (val != 17) {
            throw new FileVersionException(GDMsgFormatter.getString(GDMsgFormatter.rbMsg, "ERR_UNSUPPORTED_VERSION"));
        }
        this.version = GDReader.readEncInt(true);
        if (this.version != 2) {
            throw new FileVersionException(GDMsgFormatter.getString(GDMsgFormatter.rbMsg, "ERR_UNSUPPORTED_VERSION"));
        }
        for (int i = 0; i < this.uidLists.size(); ++i) {
            GDChar.readUIDList(this.uidLists.get(i));
        }
        GDReader.readBlockEnd(block);
        this.changed = false;
    }

    public void write() throws IOException {
        final GDReader.Block block = new GDReader.Block();
        GDWriter.writeBlockStart(block, 17);
        GDWriter.writeInt(2);
        for (int i = 0; i < this.uidLists.size(); ++i) {
            GDChar.writeUIDList(this.uidLists.get(i));
        }
        GDWriter.writeBlockEnd(block);
        this.changed = false;
    }

    public int getByteSize() {
        int size = 0;
        size += 4;
        size += 4;
        size += 4;
        for (int i = 0; i < this.uidLists.size(); ++i) {
            size += 4;
            size += this.uidLists.get(i).size() * GDCharUID.getByteSize();
        }
        size += 4;
        return size;
    }

    public void print() {
        for (int i = 0; i < this.uidLists.size(); ++i) {
            System.out.println("Index : " + Integer.toString(i));
            for (final GDCharUID uid : this.uidLists.get(i)) {
                uid.println();
            }
            System.out.println();
        }
    }
}
